
from django.db.models import Count,Q
from rest_framework import request,status
from rest_framework.filters import SearchFilter
from rest_framework.generics import ListCreateAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.views import APIView,Response
from django.contrib.auth.hashers import check_password, make_password
from django.http import HttpResponse
from captcha.image import ImageCaptcha
from rest_framework.viewsets import ModelViewSet

from myapp.models import UserModel, MenuModel, DepartmentModel, LoginLogModel, RoleMenuModel, RoleModel, \
    ProcessInsModel, OperationLogModel
from process.serializer import ProcessSer
from utils.ip_address.ip_info import CzIp
from utils.jwt_token import _generate_token
from utils.force_login import check_login
from myapp.serializer import UserSer, MenuSer, LoginLogSer, OperationLogSer
from role.serializer import DepartmentSer,RoleMenuSer
import datetime
import string
import random
import redis

from utils.login_util import operation_log


class MyPagination(PageNumberPagination):
    # 默认每页显示的条数
    page_size = 2
    # 每页最大显示 的条数
    max_page_size = 10

    # 根据查询字符串的关键字参数   http://localhost:8000/users/?page=2&pagesize=5
    # 页码
    page_query_param = "page"

    # 每页展示多少条数据
    page_size_query_param = "pagesize"

# 生成图片验证码
class Image(APIView):
    def get(self,request, uuid):
        # 生成随机字符串
        code_str = "".join(random.sample(string.ascii_letters + string.digits, 4))
        print("字符码:", code_str)

        # 存储随机字符串
        redis_conn = redis.Redis(host="localhost", port=6379, db=0,)
        key = "imageCode:%s"%uuid
        redis_conn.set(key, code_str, ex=300)
        redis_conn.close()

        # 图片验证码
        captcha_obj = ImageCaptcha()
        image_captcha = captcha_obj.generate(code_str)  # BytesIO对象， 类似于文件对象

        print(image_captcha)

        return HttpResponse(image_captcha, content_type="image/png")

#登录
class LoginAPIView(APIView):
    def post(self,request):
        account = request.data.get('account')
        password  = request.data.get('password')
        img_code = request.data.get('message_code')
        uuid = request.data.get('uuid')
        user = UserModel.objects.get(account=account)
        if not user:
            return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'用户名不存在'})
        user = UserModel.objects.get(account=account)
        user_ser = UserSer(user)
        print('>>>>>>', user.id)
        redis_conn = redis.Redis(host="localhost", port=6379, db=0)
        key = "imageCode:%s"%uuid
        sms_code = redis_conn.get(key)
        print(sms_code)
        if not sms_code:
            return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'验证码过期'})
        if not sms_code.decode() == img_code:
            return Response({"code":status.HTTP_400_BAD_REQUEST,'msg':'验证码错误'})
        redis_conn.close()
        if user:
            if (password==user.password):
                data = {
                    'user_id':user.id,
                    'user_name':user.username
                }
                token, refresh_token = _generate_token(data)
                if request.META.get('HTTP_X_FORWARDED_FOR'):
                    ip = request.META.get('HTTP_X_FORWARDED_FOR')
                else:
                    ip = request.META.get('REMOTE_ADDR')
                print('======================', ip)
                # 设备的信息
                print(type(request))  # <class 'django.core.handlers.wsgi.WSGIRequest'>
                system = request.environ.get("HTTP_USER_AGENT")[:200]
                print('设备信息：', system[:200])  # 全部返回的是个字典
                crea = user.create_time = datetime.datetime.now()  # 更新登录时间
                # 获取登陆地址
                cz = CzIp()
                places = cz.get_addr_by_ip(ip)
                # 开始写入登陆日志
                LoginLogModel.objects.create(user_id=user.id, ip=ip, system=system, places=places,times=crea)
                return Response({'code': status.HTTP_200_OK, 'msg': '登录成功', 'token': token,'refresh_token':refresh_token, 'user': user_ser.data})
            return Response({'code': status.HTTP_400_BAD_REQUEST, 'msg': '密码错误'})

# 修改密码
class Amendpwd(APIView):
    def put(self,request):
        account = request.data.get('account')
        password = request.data.get('password')
        confirm_password = request.data.get('confirm_password')

        user = UserModel.objects.get(account=account)
        if not user:
            return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'用户名不存在'})
        if not password == confirm_password:
            return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'两次密码不一样'})
        user = UserModel.objects.filter(account=account).update(password=password)

        return Response({"code":status.HTTP_200_OK,'msg':'修改成功'})

# 菜单管理
class MenuBarViews(APIView):
    @check_login
    def get(self, request):
        user = request.session.get('user')
        uid = user['user_id']
        role = RoleModel.objects.get(id=uid)
        rolemenu= RoleMenuModel.objects.filter(role_id=role.id).all()
        # rolemenu_ser = RoleMenuSer(rolemenu,many=True).data
        data = []
        for t in rolemenu:
            print(t.menu_id)
            menus = MenuModel.objects.filter(assoc_id=None,id=t.menu_id).all()
            menus_ser = MenuSer(menus, many=True).data

            for i in menus_ser:
                # 获取父级下的所有子级
                menus2 = MenuModel.objects.filter(assoc_id=i['id']).all()
                menus2_ser = MenuSer(menus2, many=True).data
                i['submenus'] = menus2_ser
                data.append(i)

        return Response({'msg': '获取角色菜单成功', 'code': status.HTTP_200_OK, 'data': data })

    def post(self,request):
        m_name = request.data.get('m_name')
        m_route = request.data.get('m_route')
        m_typ = request.data.get('m_typ')
        icon = request.data.get('icon')
        m_sort = request.data.get('m_sort')
        comment = request.data.get('comment')
        assoc_id = request.data.get('assoc_id')

        if not assoc_id:
            if not all([m_name,m_route,icon,comment]):
                return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'信息不完整'})
            MenuModel.objects.create(m_name=m_name,m_route=m_route,icon=icon,m_typ='目录',comment=comment,m_sort=m_sort)
            return Response({'code':status.HTTP_200_OK,'msg':'添加菜单成功'})
        if not all([m_name, m_route, icon, comment,assoc_id,]):
            return Response({'code': status.HTTP_400_BAD_REQUEST, 'msg': '信息不完整'})
        MenuModel.objects.create(m_name=m_name, m_route=m_route, icon=icon, m_typ='菜单', comment=comment,assoc_id=assoc_id,m_sort=m_sort)
        operation_log(request, '添加菜单')
        return Response({'code': status.HTTP_200_OK, 'msg': '添加菜单成功'})

# 获取单个菜单
class MenuBarAPI(APIView):
    def get(self,request,pk):
        menus = MenuModel.objects.filter(Q(assoc_id=None)& Q(id=pk)).all()
        menus_ser = MenuSer(menus, many=True).data
        data = []
        for i in menus_ser:
            # 获取父级下的所有子级
            menus2 = MenuModel.objects.filter(assoc_id=i['id']).all()
            menus2_ser = MenuSer(menus2, many=True).data
            i['submenus'] = menus2_ser
            data.append(i)
        return Response({'msg': '获取成功', 'code': status.HTTP_200_OK, 'data': data})

    def put(self,request,pk):
        m_name = request.data.get('m_name')
        m_route = request.data.get('m_route')
        m_typ = request.data.get('m_typ')
        icon = request.data.get('icon')
        m_sort = request.data.get('m_sort')
        comment = request.data.get('comment')
        assoc_id = request.data.get('assoc_id')

        menu = MenuModel.objects.filter(Q(id=pk)&Q(logic_del=0))
        if menu:
            menu.update(m_name=m_name, m_route=m_route, icon=icon, m_typ=m_typ, comment=comment,
                                 assoc_id=assoc_id, m_sort=m_sort)
            operation_log(request, '修改了一个菜单')
            return Response({'code': status.HTTP_200_OK, 'msg': '修改菜单成功'})
        return Response({"code": status.HTTP_204_NO_CONTENT, 'msg': '没有该用户'})

    def delete(self,request,pk):
        menu = MenuModel.objects.filter(Q(id=pk)&Q(logic_del=0)).update(logic_del=1)
        if menu:
            operation_log(request, '删除了一个菜单')
            return Response({'code': status.HTTP_200_OK, 'msg': '删除成功'})
        return Response({"code": status.HTTP_204_NO_CONTENT, 'msg': '没有该用户'})

# 菜单的模糊查询
class MenuVague(APIView):
    def post(self,request):
        m_name = request.data.get('m_name')

        menus = MenuModel.objects.filter(m_name__contains = m_name).all()
        menus_ser = MenuSer(menus, many=True).data
        return Response({'code':status.HTTP_200_OK,'msg':'获取成功','data':menus_ser})

# 首页
class Numbers(APIView):

    def get(self,request):
        user_number = UserModel.objects.all().count() #全部员工数量
        formal_user = UserModel.objects.filter(state=2).all().count() # 正式员工数量
        practice_user = UserModel.objects.filter(state=1).all().count() # 实习生数量
        await_entry_user = UserModel.objects.filter(month_await=1).all().count() # 本月待入职
        await_dimission_user = UserModel.objects.filter(month_await=2).all().count() # 本月待离职
        await_positive_user = UserModel.objects.filter(month_await=3).all().count() # 本月待转正
        number = {
            "user_number": user_number, # 全部员工数量
            "formal_user": formal_user, # 正式员工数量
            "practice_user": practice_user, # 实习生数量
            "await_entry_user": await_entry_user, # 本月待入职
            "await_dimission_user": await_dimission_user, # 本月待离职
            "await_positive_user": await_positive_user, # 本月待转正
        }
        # 获取员工地区数量
        try:
            # 获取地区
            user = UserModel.objects.values('address').annotate(count=Count('address'))
            address = []
            for i in user:
                address.append({'address': i['address'], 'num': i['count']})
        except Exception as e:
            print('获取地区人数报错信息是', e)

        try:
            # 获取生日
            birthday = []
            for i in range(1,13):
                user = UserModel.objects.filter(birthday__month=i).all().count()
                birthday.append({'month': i, 'number': user})
        except Exception as e:
            print('获取生日人数报错信息是', e)

        try:
            backlog = []
            process = ProcessInsModel.objects.filter(state=0).all()
            process_ser = ProcessSer(process, many=True).data
            for i in process_ser:
                backlog.append({'apply':i['apply'],'apply_name':i['apply_name'],'times':i['times'],'user':i['user'],
                                'user_name':i['user_name']})
        except Exception as e:
            print('代办事项的错误信息',e)
        return Response({'msg': '获取成功', 'code': 200,
                         'data': {'number': number, 'address': address, 'birthday':birthday,'backlog':backlog}})

# 用户管理
class UserView(ListCreateAPIView):
    queryset = UserModel.objects.filter(logic_del = 0).all()
    serializer_class = UserSer
    pagination_class = MyPagination

    def post(self,request):
        username = request.data.get('username')
        account = request.data.get('account')
        password = request.data.get('password')
        phone = request.data.get('phone')
        birthday = request.data.get('birthday')
        address = request.data.get('address')
        jobs_id = request.data.get('jobs')
        department_id = request.data.get('department')
        rank_id = request.data.get('rank')
        role_id = request.data.get('role')
        if not all([username, account, password, phone, birthday, jobs_id, department_id, rank_id, role_id]):
            return Response({"msg": '数据不完整', 'code': status.HTTP_400_BAD_REQUEST})

        if UserModel.objects.filter(account=account).first():
            return Response({'msg': '用户已存在', 'code': status.HTTP_400_BAD_REQUEST})

        try:
            # hash_pwd = make_password(password)
            user = UserModel.objects.create(username=username, account=account, password=password, birthday=birthday,
                                            address=address, jobs_id=jobs_id, phone=phone, department_id=department_id,
                                            rank_id=rank_id, role_id=role_id)
            user_ser = UserSer(user).data
        except Exception as e:
            print('新增员工报错的信息是=>', e)
            return Response({'msg': e})
        operation_log(request, '添加新员工')
        return Response({'msg': '添加成功', 'code': status.HTTP_200_OK, 'data': user_ser})

# 删除用户等
class UserAPI(APIView):
    def get(self,request,pk):
        user = UserModel.objects.get(id=pk)
        if user.logic_del ==1:
            return Response({'code':status.HTTP_204_NO_CONTENT,'msg':'没有该用户'})
        user_ser = UserSer(user).data
        return Response({"code": status.HTTP_200_OK, 'msg': '获取成功', 'data': user_ser})

    def delete(self,request,pk):
        user = UserModel.objects.filter(id=pk,logic_del=0)
        if user:
            user.update(logic_del = 1)
            operation_log(request, '删除了一个员工')
            return Response({'code':status.HTTP_200_OK,'msg':'删除成功'})
        return Response({"code":status.HTTP_204_NO_CONTENT,'msg':'没有该用户'})

    def put(self,request,pk):
        username = request.data.get('username')
        account = request.data.get('account')
        password = request.data.get('password')
        phone = request.data.get('phone')
        birthday = request.data.get('birthday')
        address = request.data.get('address')
        jobs_id = request.data.get('jobs')
        department_id = request.data.get('department')
        rank_id = request.data.get('rank')
        role_id = request.data.get('role')

        if not all([username, account, password, phone, birthday, jobs_id, department_id, rank_id, role_id,address]):
            return Response({"msg": '数据不完整', 'code': status.HTTP_400_BAD_REQUEST})

        hash_pwd = make_password(password)
        user = UserModel.objects.filter(id=pk,logic_del=0)
        if not user:
            return Response({'code':status.HTTP_400_BAD_REQUEST,'msg':'没有该员工'})
        user.update(username=username, account=account, password=hash_pwd, birthday=birthday,
                                        address=address, jobs_id=jobs_id, phone=phone, department_id=department_id,
                                        rank_id=rank_id, role_id=role_id)
        operation_log(request, '修改了一个员工信息')
        return Response({"code":status.HTTP_200_OK,'msg':'修改成功'})

# 模糊查询用户
class Vague(APIView):
    def post(self,request):
        username = request.data.get('username')
        phone = request.data.get('phone')
        department = request.data.get('department')
        print(username,phone,department)

        depar = DepartmentModel.objects.filter(d_name__contains=department)
        a = ''
        for i in depar:
            print(i)
            a=i.id
        search_dict={}
        if username:
            search_dict['username'] = username
        else:
            search_dict['username'] = ""
        if phone:
            search_dict['phone'] = phone
        else:
            search_dict['phone'] = ""
        if a:
            search_dict['department'] = a
        else:
            search_dict['department'] = ""
        print(search_dict)
        user = UserModel.objects.filter(username__contains=search_dict['username'])\
            .filter(phone__contains=search_dict['phone'])\
            .filter(department__id__contains = search_dict['department'])
        user_ser =UserSer(user,many=True).data
        return Response({'code':status.HTTP_200_OK,'msg':'获取成功','data':user_ser})


#获取登录日志
class LoginLogsView(ListCreateAPIView):
    queryset = LoginLogModel.objects.filter(logic_del=0).all()
    serializer_class = LoginLogSer
    pagination_class = MyPagination
    filter_backends = [SearchFilter]
    search_fields = ['account',]

class LoginLogView(APIView):
    def get(self,request,pk):
        try:
            log = LoginLogModel.objects.filter(id=pk).first()
            ser = LoginLogSer(log).data
            return Response({"code":status.HTTP_200_OK,'msg':'获取成功','data':ser})
        except Exception as e:
            print("错误信息",e)
            return Response({"code":status.HTTP_500_INTERNAL_SERVER_ERROR,'msg':'获取失败'})


# 操作日志
class OperationLogAPIView(ListCreateAPIView):
    queryset = OperationLogModel.objects.filter(logic_del=0).all()
    serializer_class = OperationLogSer
    pagination_class = MyPagination


class OperationLogAPI(APIView):
    def get(self,request,pk):
        try:
            log = OperationLogModel.objects.filter(id=pk,logic_del=0).first()
            ser = OperationLogSer(log).data
            return Response({"code":status.HTTP_200_OK,'msg':'获取成功','data':ser})
        except Exception as e:
            print("错误信息",e)
            return Response({"code":status.HTTP_500_INTERNAL_SERVER_ERROR,'msg':'获取失败'})